# -*- coding: utf-8 -*-
from datetime import datetime, timedelta
from typing import Dict, Optional, List

from dateutil.relativedelta import relativedelta
from sqlalchemy import or_, and_
from jose import jwt, ExpiredSignatureError

from configs import SECRET_KEY, ALGORITHM, ACCESS_TOKEN_EXPIRE_MINUTES, GUEST_GROUP_ID, GUEST_DEFAULT_VALIDITY_PERIOD, REFRESH_DELTA_MINUTES
from db.session import with_session
from db.models.user import User, Group, UserGroup, GroupPermission


""" =========================== User ================================ """


# 创建token
def create_access_token(data: dict, expires_delta: timedelta = None):
    to_encode = data.copy()
    expire = datetime.now() + (expires_delta if expires_delta else timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
    to_encode.update({"exp": expire})
    encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
    return encoded_jwt


# 根据用户名获取用户
@with_session
def db_get_user_by_username(session, username, is_delete=None):
    if is_delete is None:
        return session.query(User)\
            .filter(User.username == username)\
            .first()
    else:
        return session.query(User)\
            .filter(User.username == username, User.is_delete.is_(is_delete))\
            .first()


# 更新token
@with_session
def db_update_user_token(session, user_id, token):
    user = session.query(User).get(user_id)
    if not user:
        return None
    user.token = token
    session.commit()
    return user


# 验证token
@with_session
def db_check_refresh_user_token(session, username: str, payload: Dict) -> Optional[User]:
    """统一处理token获取和更新"""
    user = session.query(User).filter(User.username == username, User.is_delete.is_(False)).first()

    if not user:
        return None

    # 解析现有token
    try:
        exp = datetime.utcfromtimestamp(payload["exp"])
        now = datetime.utcnow()  # 统一使用UTC时间
        if (exp - now) < timedelta(minutes=30):
            new_token = create_access_token(
                data={"name": user.username},
                expires_delta=timedelta(minutes=REFRESH_DELTA_MINUTES)
            )
            user.token = new_token

    except Exception as e:
        session.rollback()
        return None

    return user


# 查验用户权限
@with_session
def db_check_user_permission(session, user: User, permission: str):
    if user.role == "superman":
        return True

    current_time = datetime.now()
    has_permission = (session.query(GroupPermission)
                        .join(Group, GroupPermission.group == Group.id)
                        .join(UserGroup, GroupPermission.group ==UserGroup.group)
                        .join(User, UserGroup.user == User.id)
                        .filter(User.id == user.id,
                                User.is_delete.is_(False),
                                GroupPermission.permission == permission,
                                or_(
                                    # 当 group_id 为 GUEST_GROUP_ID 时，为临时用户组，检查 user.create_time + 3天 是否小于当前时间
                                    and_(
                                        Group.id == GUEST_GROUP_ID,
                                        (User.create_time + relativedelta(days=GUEST_DEFAULT_VALIDITY_PERIOD)) > current_time
                                    ),
                                    # 其他 group_id，检查 过期时间 是否大于当前时间
                                    and_(
                                        Group.id != GUEST_GROUP_ID,
                                        Group.expiration_time > current_time
                                    )
                                ))
                        .first())
    # print(self.to_json(), has_permission)
    if has_permission is None:
        return False


@with_session
def db_create_user(session, payload):
    user = User(username=payload.username,
                nickname=payload.nickname,
                password=payload.password,
                company=payload.company
                )
    session.add(user)
    session.commit()
    return user


""" =========================== Group ================================ """


# 获取用户的用户组id
@with_session
def db_get_user_group_ids(session, user: User):
    if user.role in ["superman"]:
        user_groups = session.query(Group.id) \
            .filter(Group.is_delete.is_(False)) \
            .all()
    else:
        user_groups = session.query(UserGroup.group) \
            .filter(UserGroup.user == user.id) \
            .distinct() \
            .all()
    user_groups = [i[0] for i in user_groups]
    return user_groups


# 超级管理员获取所有用户组
@with_session
def db_get_groups_for_superadmin(session) -> List[Group]:
    """获取超级管理员可见的所有组"""
    return session.query(Group).filter(Group.is_delete.is_(False)).all()


# 通过组id获取组信息 列表
@with_session
def db_get_groups_by_ids(session, g_ids):
    files = session.query(Group).filter(Group.id.in_(g_ids)).all()
    g_dict = dict()
    for f in files:
        g_dict[f.id] = f.name
    return g_dict


# 通过组id获取组信息
@with_session
def db_get_group_by_id(session, g_id, user: User):
    if user.check_superman_role():
        group: Group = session.query(Group) \
            .filter(Group.id == g_id, Group.is_delete.is_(False)) \
            .first()
    elif user.check_admin_role():
        group: Group = session.query(Group) \
            .join(UserGroup, Group.id == UserGroup.group) \
            .filter(Group.id == g_id, UserGroup.user == user.id, Group.is_delete.is_(False)) \
            .first()
    else:
        group: Group = session.query(Group) \
            .filter(Group.owner == user.id, Group.id == g_id, Group.is_delete.is_(False)) \
            .first()
    return group


@with_session
def db_get_groups_for_user(session, user_id: int) -> List[Group]:
    """获取普通用户可见的组"""
    return session.query(Group)\
        .join(UserGroup, Group.id == UserGroup.group)\
        .filter(UserGroup.user == user_id, Group.is_delete.is_(False))\
        .all()


""" =========================== UserGroup ================================ """


@with_session
def db_delete_user_group_by_user(session, user_id):
    session.query(UserGroup)\
        .filter(UserGroup.user == user_id)\
        .delete()
    session.commit()
    return True


@with_session
def db_create_user_group(session, user_id, group_id):
    db_user_group = UserGroup(user=user_id, group=group_id)
    session.add(db_user_group)
    session.commit()
    session.refresh(db_user_group)
    return db_user_group


# 获取用户有权限访问的组ID列表
@with_session
def db_get_ugs_by_ids(session, group_ids, user_id=None):
    query = session.query(UserGroup.group).filter(UserGroup.group.in_(group_ids))
    if user_id:
        query = query.filter(UserGroup.user == user_id)
    return [group[0] for group in query.distinct().all()]


def filter_groups_by_name(groups: List[Group], name_prefix: Optional[str]) -> List[Group]:
    """根据名称前缀过滤组列表"""
    if not name_prefix:
        return groups
    return [group for group in groups if group.name.startswith(name_prefix)]


# ==================== 用户管理相关函数 ====================

@with_session
def db_search_users(session, username: str = None, user_groups: List[int] = None, user_ids: List[int] = None):
    """搜索用户"""
    if user_groups:
        # 根据用户组搜索
        query = session.query(User).join(UserGroup, UserGroup.user == User.id).filter(
            User.is_delete.is_(False),
            UserGroup.group.in_(user_groups)
        ).distinct()
    else:
        # 搜索所有用户
        query = session.query(User).filter(User.is_delete.is_(False))
    
    if username:
        query = query.filter(User.nickname.startswith(username))

    if user_ids:
        query = query.filter(User.id.in_(user_ids))
    
    return query.all()


@with_session
def db_get_user_by_id(session, user_id: int):
    """根据ID获取用户"""
    return session.query(User).filter(User.id == user_id, User.is_delete.is_(False)).first()


@with_session
def db_soft_delete_user(session, user_id: int):
    """软删除用户"""
    user = session.query(User).get(user_id)
    if user:
        user.is_delete = True
        user.updated_time = datetime.now()
        session.commit()
        return True
    return False


@with_session
def db_remove_user_from_all_groups(session, user_id: int):
    """从所有组中移除用户"""
    session.query(UserGroup).filter(UserGroup.user == user_id).delete()
    session.commit()


@with_session
def db_update_user(session, user_id: int, nickname: str = None, company: str = None, password: str = None, role: str = None):
    """更新用户信息"""
    user = session.query(User).get(user_id)
    if not user:
        return None
    
    if nickname:
        user.nickname = nickname
    if company is not None:
        user.company = company
    if password:
        user.password = password
        user.encry_password()
    if role:
        user.role = role
        user.is_admin = role != "normal"
    
    user.updated_time = datetime.now()
    session.commit()
    return user


@with_session
def db_create_user(session, username: str, nickname: str, password: str, 
                  company: str = None, role: str = "normal"):
    """创建用户"""
    user = User(
        username=username,
        nickname=nickname,
        password=password,
        company=company,
        role=role,
        is_admin=role != "normal"
    )
    user.encry_password()
    session.add(user)
    session.flush()
    return user


@with_session
def db_check_user_exists(session, username: str):
    """检查用户是否存在"""
    return session.query(User).filter(User.username == username).first()


@with_session
def db_restore_user(session, username: str, nickname: str, password: str, 
                   company: str = None, role: str = "normal"):
    """恢复已删除的用户"""
    user = session.query(User).filter(User.username == username).first()
    if user and user.is_delete:
        user.is_delete = False
        user.nickname = nickname
        user.password = password
        user.company = company
        user.role = role
        user.is_admin = role != "normal"
        user.encry_password()
        user.updated_time = datetime.now()
        session.commit()
        return user
    return None


@with_session
def db_check_user_in_group(session, user_id: int, group_id: int):
    """检查用户是否在组中"""
    return session.query(UserGroup).filter(
        UserGroup.user == user_id,
        UserGroup.group == group_id
    ).first()


@with_session
def db_add_user_to_group(session, user_id: int, group_id: int):
    """将用户添加到组"""
    user_group = UserGroup(user=user_id, group=group_id)
    session.add(user_group)
    session.commit()
    return user_group


@with_session
def db_bulk_add_users_to_group(session, user_ids: List[int], group_id: int):
    """批量将用户添加到组"""
    user_groups = [UserGroup(user=user_id, group=group_id) for user_id in user_ids]
    session.bulk_save_objects(user_groups)
    session.commit()
    return user_groups


@with_session
def db_get_user_groups(session, user_id: int):
    """获取用户所属的组"""
    return session.query(Group).join(UserGroup, Group.id == UserGroup.group).filter(
        UserGroup.user == user_id,
        Group.is_delete.is_(False)
    ).all()


@with_session
def db_get_user_permissions(session, user_id: int, user_groups: List[int] = None):
    """获取用户权限"""
    if user_groups:
        permissions = session.query(GroupPermission.permission).join(UserGroup,
            GroupPermission.group == UserGroup.group).join(User,
            UserGroup.user == User.id).filter(
            UserGroup.group.in_(user_groups),
            User.id == user_id,
            User.is_delete.is_(False)
        ).distinct().all()
    else:
        permissions = session.query(GroupPermission.permission).join(UserGroup,
            GroupPermission.group == UserGroup.group).join(User,
            UserGroup.user == User.id).filter(
            User.id == user_id,
            User.is_delete.is_(False)
        ).distinct().all()
    
    return [p[0] for p in permissions]
